﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace BPMS.Utility.Reflections
{
    public static class ReflectionUtility
    {
        public static readonly BindingFlags AllFlags;
        public static readonly BindingFlags StaticFlags;
        public static readonly BindingFlags Instanceslags;

        static ReflectionUtility()
        {
            AllFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
            StaticFlags = BindingFlags.Public | BindingFlags.Static;
            Instanceslags = BindingFlags.Public | BindingFlags.Instance;
        }

        public static ConstructorInfo GetNoParameterConstructor(Type type)
        {
            return type.GetConstructor(Instanceslags, null, new Type[] { }, null);
        }

        public static List<ConstructorInfo> GetPublicConstructor(Type type)
        {
            List<ConstructorInfo> list = new List<ConstructorInfo>();
            var constructors = type.GetConstructors(Instanceslags);
            foreach (var item in constructors)
            {
                if (item.IsPublic)
                {
                    list.Add(item);
                }
            }
            return list;
        }

        public static object CreateInstance<T>()
        {
            return Activator.CreateInstance<T>();
        }

        public static object CreateInstance<T>(params object[] parameters)
        {
            return Activator.CreateInstance(typeof(T), parameters);
        }

        public static object CreateInstance(string className)
        {
            return Activator.CreateInstance(Type.GetType(className, true));
        }

        public static object CreateInstance(string className, params object[] parameters)
        {
            return Activator.CreateInstance(Type.GetType(className, true), parameters);
        }

        public static object CreateInstance(Assembly frmAssembly, string className)
        {
            return Activator.CreateInstance(frmAssembly.GetType(className, true));
        }

        public static object InvokeMethod<T>(string functionName, params object[] parameters)
        {
            var method = typeof(T).GetMethod(functionName, AllFlags, null, CallingConventions.Any, GetTypes(parameters), null);
            if (null == method)
                return null;
            return method.Invoke(null, parameters);
        }

        public static object InvokeMethod(object obj, string functionName, params object[] parameters)
        {
            var method = obj.GetType().GetMethod(functionName, AllFlags, null, CallingConventions.Any, GetTypes(parameters), null);
            if (null == method)
                return null;
            return method.Invoke(obj, parameters);
        }

        public static Type[] GetTypes(params object[] objects)
        {
            List<Type> types = new List<Type>();
            foreach (object item in objects)
            {
                types.Add(item.GetType());
            }
            return types.ToArray();
        }

        public static Type GetType<T>()
        {
            Type type = typeof(T);
            if (type.IsGenericType)
            {
                type = type.GetGenericArguments()[0];
            }
            return type;
        }

        public static T[] GetAttributes<T>(this MethodInfo info, bool inherit) where T : Attribute
        {
            var os = info.GetCustomAttributes(typeof(T), inherit);
            return (T[])os;
        }

        public static T GetAttribute<T>(this MethodInfo info, bool inherit) where T : Attribute
        {
            var ts = GetAttributes<T>(info, inherit);
            if (ts != null && ts.Length > 0)
                return ts[0];
            return null;
        }

        public static T[] GetAttributes<T>(this FieldInfo info, bool inherit) where T : Attribute
        {
            var os = info.GetCustomAttributes(typeof(T), inherit);
            return (T[])os;
        }

        public static T GetAttribute<T>(this FieldInfo info, bool inherit) where T : Attribute
        {
            var ts = GetAttributes<T>(info, inherit);
            if (ts != null && ts.Length > 0)
                return ts[0];
            return null;
        }

        public static T[] GetAttributes<T>(this PropertyInfo info, bool inherit) where T : Attribute
        {
            var os = info.GetCustomAttributes(typeof(T), inherit);
            return (T[])os;
        }

        public static T GetAttribute<T>(this PropertyInfo info, bool inherit) where T : Attribute
        {
            var ts = GetAttributes<T>(info, inherit);
            if (ts != null && ts.Length > 0)
                return ts[0];
            return null;
        }

        public static T[] GetAttributes<T>(this Type info, bool inherit) where T : Attribute
        {
            var os = info.GetCustomAttributes(typeof(T), inherit);
            return (T[])os;
        }

        public static T GetAttribute<T>(this Type info, bool inherit) where T : Attribute
        {
            var ts = GetAttributes<T>(info, inherit);
            if (ts != null && ts.Length > 0)
                return ts[0];
            return null;
        }

        public static T[] GetAttributes<T>(this ParameterInfo info, bool inherit) where T : Attribute
        {
            var os = info.GetCustomAttributes(typeof(T), inherit);
            return (T[])os;
        }

        public static T GetAttribute<T>(this ParameterInfo info, bool inherit) where T : Attribute
        {
            var ts = GetAttributes<T>(info, inherit);
            if (ts != null && ts.Length > 0)
                return ts[0];
            return null;
        }

        public static bool HasAttribute<T>(this MethodInfo info, bool inherit) where T : Attribute
        {
            return GetAttribute<T>(info, inherit) != null;
        }

        public static bool HasAttribute<T>(this FieldInfo info, bool inherit) where T : Attribute
        {
            return GetAttribute<T>(info, inherit) != null;
        }

        public static bool HasAttribute<T>(this PropertyInfo info, bool inherit) where T : Attribute
        {
            return GetAttribute<T>(info, inherit) != null;
        }

        public static bool HasAttribute<T>(this Type info, bool inherit) where T : Attribute
        {
            return GetAttribute<T>(info, inherit) != null;
        }

        public static bool HasAttribute<T>(this ParameterInfo info, bool inherit) where T : Attribute
        {
            return GetAttribute<T>(info, inherit) != null;
        }

        public static bool IsChildOf(this Type tc, Type tf)
        {
            if (tf.IsInterface)
            {
                return tc.GetInterfaces().Any(type => type.Equals(tf));
            }
            return tc.IsSubclassOf(tf);
        }
    }
}
